package by.pavlyukevich.paymentsystem.panel.card;

import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.event.Broadcast;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.hibernate.LazyInitializationException;
import org.springframework.orm.jpa.JpaSystemException;

import by.pavlyukevich.paymentsystem.add.AbstractDataProvider;
import by.pavlyukevich.paymentsystem.add.AdminAjaxLink;
import by.pavlyukevich.paymentsystem.add.ErrorEvent;
import by.pavlyukevich.paymentsystem.add.PanelUpdateEvent;
import by.pavlyukevich.paymentsystem.add.SelectEvent;
import by.pavlyukevich.paymentsystem.add.UpdateEvent;
import by.pavlyukevich.paymentsystem.add.UserAjaxLink;
import by.pavlyukevich.paymentsystem.dataaccess.filter.AccountFilter;
import by.pavlyukevich.paymentsystem.dataaccess.filter.CardFilter;
import by.pavlyukevich.paymentsystem.dataaccess.filter.CardLimitFilter;
import by.pavlyukevich.paymentsystem.dataaccess.filter.Filter;
import by.pavlyukevich.paymentsystem.datamodel.Account;
import by.pavlyukevich.paymentsystem.datamodel.card.Card;
import by.pavlyukevich.paymentsystem.datamodel.card.Card_;
import by.pavlyukevich.paymentsystem.panel.AccountEditPanel;
import by.pavlyukevich.paymentsystem.panel.MyPagingNavigator;
import by.pavlyukevich.paymentsystem.panel.user.IndividualEditPanel;
import by.pavlyukevich.paymentsystem.services.AccountService;
import by.pavlyukevich.paymentsystem.services.card.CardService;
import by.pavlyukevich.paymentsystem.webapp.BasicAuthenticationSession;

public class CardListPanel extends Panel {

	@Inject
	private CardService cardService;
	@Inject
	private AccountService accountService;
	private CardFilter cardFilter;
	private Panel respPanel;

	public CardListPanel(String id) {
		this(id, new CardFilter());
	}

	public CardListPanel(String id, CardFilter cardFilter) {
		super(id);
		this.cardFilter = cardFilter;
		this.respPanel = this;
	}

	@Override
	protected void onInitialize() {
		setOutputMarkupId(true);

		boolean isAdmin = BasicAuthenticationSession.get().getRoles().contains("ADMIN");

		CardDataProvider cardDP = new CardDataProvider(Card_.cardNumber, cardFilter);

		final WebMarkupContainer cardTable = new WebMarkupContainer("card-table");
		cardTable.setOutputMarkupId(true);
		add(cardTable);

		DataView<Card> dataView = new DataView<Card>("card-row", cardDP, 20) {

			@Override
			protected void populateItem(Item<Card> item) {

				// TODO change query
				Card cardDb = item.getModelObject();
				try {
					cardDb.getAccount().getAccountNumber();
				} catch (LazyInitializationException e) {
					cardDb = cardService.getList(new CardFilter().setCard(cardDb)).get(0);
				}
				final Card card = cardDb;

				item.add(new Label("cardNumber"));

				AjaxLink<Void> accountLink = new AjaxLink<Void>("account") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target,
								new AccountEditPanel("ac-panel", card.getAccount(), respPanel)));
					}
				};
				item.add(accountLink.setBody(
						new Model<String>(card.getAccount().getAccountNumber().toString()))
						.setEnabled(isAdmin));

				item.add(new CheckBox("isBlocked").setEnabled(false));

				AjaxLink<Void> userAccountLink = new AjaxLink<Void>("userAccount") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target,
								new IndividualEditPanel("ac-panel", card.getUserAccount()
										.getIndividual(), respPanel)));
					}
				};
				userAccountLink.setBody(new Model<String>(card.getUserAccount().getIndividual()
						.getFamily()
						+ " " + card.getUserAccount().getIndividual().getName()));
				item.add(userAccountLink.setEnabled(isAdmin));

				item.add(new AjaxLink<Void>("cardLimits") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						Account account = accountService.getList(
								new AccountFilter().setAccount(card.getAccount())).get(0);
						if ((account.getUserAccount().equals(BasicAuthenticationSession.get()
								.getUserAccount())) || isAdmin) {

							send(getPage(), Broadcast.BREADTH,
									new PanelUpdateEvent(target, new CardLimitListPanel("ac-panel",
											new CardLimitFilter().setCard(card))));
						} else {
							error(new ResourceModel("t.error.unableToChange").getObject());
							send(getPage(), Broadcast.BREADTH, new ErrorEvent(target));
						}
					}
				});

				item.add(new AdminAjaxLink<Void>("delete") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						try {
							cardService.delete(card);
							target.add(respPanel);
						} catch (JpaSystemException e) {
							error(new ResourceModel("t.error.unableToDelete").getObject());
							send(getPage(), Broadcast.BREADTH, new ErrorEvent(target));
						}

					}
				});

				item.add(new AdminAjaxLink<Void>("edit") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target,
								new CardEditPanel("ac-panel", card, respPanel)));
					}
				});

				item.add(new UserAjaxLink<Void>("select") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						send(getPage(), Broadcast.BREADTH, new SelectEvent(target, card));
					}
				});

				UserAjaxLink<Void> blockLink = new UserAjaxLink<Void>("block") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						Account account = accountService.getList(
								new AccountFilter().setAccount(card.getAccount())).get(0);
						if (account.getUserAccount().equals(
								BasicAuthenticationSession.get().getUserAccount())) {
							card.setIsBlocked(!(card.getIsBlocked()));
							cardService.saveOrUpdate(card);
							send(getPage(), Broadcast.BREADTH, new UpdateEvent(target, card));
						} else {
							error(new ResourceModel("t.error.unableToBlock").getObject());
							send(getPage(), Broadcast.BREADTH, new ErrorEvent(target));
						}

					}
				};
				item.add(blockLink);
				blockLink.setBody(new ResourceModel((card.getIsBlocked() == true) ? "b.unblock"
						: "b.block"));
			}

		};

		cardTable.add(dataView);
		add(new AdminAjaxLink<Void>("new") {

			@Override
			public void onClick(AjaxRequestTarget target) {
				Card card = new Card();
				card.setAccount(cardFilter.getAccount());
				card.setUserAccount(cardFilter.getUserAccount());
				send(getPage(), Broadcast.BREADTH, new PanelUpdateEvent(target, new CardEditPanel(
						"ac-panel", card, respPanel)));
			}
		});

		add(new MyPagingNavigator("paging", dataView));

		add(new OrderByBorder<SingularAttribute<Card, ?>>("sortByCardNumber", Card_.cardNumber,
				cardDP));

		super.onInitialize();
	};

	private class CardDataProvider extends AbstractDataProvider<Card> {
		public CardDataProvider(SingularAttribute<Card, ?> sortParam, Filter<Card> filter) {
			super(sortParam, filter, cardService);
		}
	};

}
